﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Farigola.Engine.SystemData.Entity.Type;
using Farigola.Engine.SystemData.Entity.inst;

namespace Farigola.Engine.TestUnit
{
    /// <summary>
    /// Test entity class, type and instance.
    /// </summary>
    [TestFixture]
    public class EntityClassTestUnit
    {
         /**
	     * Create a typeClass and find it.
	     * under the root_folder.
	     */
	    [Test]
	    public void testTypeClassCreateUnderRootFolderAndFind() {
            Engine engine = EngineCommonTestUnit.CreateInitEngine();
            Workspace wksp = engine.GetWorkspace();
		
		    // create a project
		    Project prj= wksp.CreateActiveProject("prj");

		    // create a type class
		    EntTypeClass typeClassAdr= prj.createTypeClass(null,"Adr");
		    Assert.IsNotNull(typeClassAdr,"The typeClass 'Adr' should be created.");
				
		    // get the tool to find entities in the project
		    EntityFinder entFinder= prj.GetEntityFinder();
		
		    // find the type class, by the name, scan recursilvy
		    EntTypeClass typeClassAdrFind =entFinder.FindEntTypeClassByName(EntityFinder.FindSystemUserType.User, prj.GetRootFolder(), "Adr",true);		
		    Assert.IsNotNull(typeClassAdrFind, "The typeClass 'Adr' should be found.");
		
		    // check that the typeClass has not data member
		    Assert.AreEqual(0, typeClassAdrFind.listDataMemberSize(), "The typeClass 'Adr' should have no data member.");
		    Assert.AreEqual(0, typeClassAdrFind.listDataMember().Count, "The typeClass 'Adr' should have no data member (2).");
	    }

	    /**
	     * Create a typeClass and find it.
	     * under the root_folder_user!
	     * implicit.
	     */
	    [Test]
	    public void testTypeClassCreateUnderRootFolderUserAndFind() {
            Engine engine = EngineCommonTestUnit.CreateInitEngine();
            Workspace wksp = engine.GetWorkspace();
		
		    // create a project
		    Project prj= wksp.CreateActiveProject("prj");

		    // create a type class
		    EntTypeClass typeClassAdr= prj.createTypeClass(prj.GetRootUserFolder(),"Adr");
		    Assert.IsNotNull(typeClassAdr, "The typeClass 'Adr' should be created.");
				
		    // get the tool to find entities in the project
		    EntityFinder entFinder= prj.GetEntityFinder();
		
		    // find the type class, by the name, scan recursilvy
		    EntTypeClass typeClassAdrFind =entFinder.FindEntTypeClassByName("Adr");		
		    Assert.IsNotNull(typeClassAdrFind, "The typeClass 'Adr' should be found.");
		
		    // check that the typeClass has not data member
		    Assert.AreEqual(0, typeClassAdrFind.listDataMemberSize(), "The typeClass 'Adr' should have no data member.");
		    Assert.AreEqual(0, typeClassAdrFind.listDataMember().Count, "The typeClass 'Adr' should have no data member (2).");
	    }

	    /**
	     * Create a typeClass and find it.
	     * under the root_folder_user!
	     * implicit.
	     */
	    [Test]
	    public void testTypeClassCreateAndFind() {
            Engine engine = EngineCommonTestUnit.CreateInitEngine();
            Workspace wksp = engine.GetWorkspace();
		
		    // create a project
		    Project prj= wksp.CreateActiveProject("prj");

		    // create a type class
		    EntTypeClass typeClassAdr= prj.CreateTypeClass("Adr");
		    Assert.IsNotNull(typeClassAdr,"The typeClass 'Adr' should be created.");
				
		    // get the tool to find entities in the project
		    EntityFinder entFinder= prj.GetEntityFinder();
		
		    // find the type class, by the name, scan recursilvy
		    EntTypeClass typeClassAdrFind =entFinder.FindEntTypeClassByName("Adr");		
		    Assert.IsNotNull(typeClassAdrFind, "The typeClass 'Adr' should be found.");
		
		    // check that the typeClass has not data member
		    Assert.AreEqual(0, typeClassAdrFind.listDataMemberSize(),"The typeClass 'Adr' should have no data member.");
		    Assert.AreEqual(0, typeClassAdrFind.listDataMember().Count,"The typeClass 'Adr' should have no data member (2).");
	    }
	
	    /**
	     * Create 2 typeClass with the same name: not possible, error.
	     */
	    [Test]
	    public void testTypeClassCreateTwoWithSameNameError() {
            Engine engine = EngineCommonTestUnit.CreateInitEngine();
            Workspace wksp = engine.GetWorkspace();
		
		    // create a project
		    Project prj= wksp.CreateActiveProject("prj");

		    // create a type class
		    EntTypeClass typeClassAdr= prj.CreateTypeClass("Adr");
		    Assert.IsNotNull(typeClassAdr, "The typeClass 'Adr' should be created.");
				
		    // create another type class with the same name: already exists
		    EntTypeClass typeClassAdr2= prj.CreateTypeClass("Adr");
		    Assert.IsNull(typeClassAdr2, "The typeClass 'Adr' can't be created, already exists.");
		
		    // get the tool to find entities in the project
		    EntityFinder entFinder= prj.GetEntityFinder();
		
		    // find the type class, by the name, scan recursilvy
		    EntTypeClass typeClassAdrFind =entFinder.FindEntTypeClassByName("Adr");		
		    Assert.IsNotNull(typeClassAdrFind, "The typeClass 'Adr' should be found.");
	    }
	
	    /**
	     * basic test, create a typeClass with some DM. 
	     */
	    [Test]
	    public void testTypeClassCreateDM() {
            Engine engine = EngineCommonTestUnit.CreateInitEngine();
            Workspace wksp = engine.GetWorkspace();
		
		    // create a project
		    Project prj= wksp.CreateActiveProject("prj");

		    // create a type class
		    EntTypeClass typeClassAdr= prj.CreateTypeClass("Adr");
		    Assert.IsNotNull(typeClassAdr, "The typeClass 'Adr' should be created.");
		
		    // add data members: street-string, town-string
		    EntTypeClassDataMember dmStreet= prj.AddTypeClassDataMember(typeClassAdr, "street", "string");
		    Assert.IsNotNull(dmStreet, "The data member 'Street' of the typeClass should exists.");
		    EntTypeClassDataMember dmTown= prj.AddTypeClassDataMember(typeClassAdr, "Town", "string");
		    Assert.IsNotNull(dmTown, "The data member 'Town' of the typeClass should exists.");
		
		    // get the tool to find entities in the project
		    EntityFinder entFinder= prj.GetEntityFinder();
		
		    // find the type class, by the name, scan recursilvy
		    EntTypeClass typeClassAdrFind =entFinder.FindEntTypeClassByName("Adr");		
		    Assert.IsNotNull(typeClassAdrFind, "The typeClass 'Adr' should be found.");
		
		    // check data members
		    EntTypeClassDataMember dmStreetFind= entFinder.FindTypeClassDataMemberByName(typeClassAdrFind, "street");
		    Assert.IsNotNull(dmStreetFind, "The data member 'Street' of the typeClass should exists.");
	    }
	
	    /**
	     create a typeClass, and 2 DM but with the same name, its not possible, error. 
	     */
	    [Test]
	    public void testTypeClassCreate2DMSameNameError() {
            Engine engine = EngineCommonTestUnit.CreateInitEngine();
            Workspace wksp = engine.GetWorkspace();
		
		    // create a project
		    Project prj= wksp.CreateActiveProject("prj");

		    // create a type class
		    EntTypeClass typeClassAdr= prj.CreateTypeClass("Adr");
		    Assert.IsNotNull(typeClassAdr, "The typeClass 'Adr' should be created.");
		
		    // add data members: street-string, town-string
		    EntTypeClassDataMember dmStreet= prj.AddTypeClassDataMember(typeClassAdr, "street", "string");
		    Assert.IsNotNull(dmStreet, "The data member 'Street' of the typeClass should exists.");
		
		    // try create a DM with the same name ->error, return null
		    EntTypeClassDataMember dmStreet2= prj.AddTypeClassDataMember(typeClassAdr, "street", "string");
		    Assert.IsNull(dmStreet2, "The data member 'street' of the typeClass should already exists, can't create it again.");
		
		    // get the tool to find entities in the project
		    EntityFinder entFinder= prj.GetEntityFinder();
		
		    // find the type class, by the name, scan recursilvy
		    EntTypeClass typeClassAdrFind =entFinder.FindEntTypeClassByName("Adr");		
		    Assert.IsNotNull(typeClassAdrFind, "The typeClass 'Adr' should be found.");
	    }
	
	    /**
	     * create an empty typeClass (no DM) and then create an inst of this type class. 
	     */
	    [Test]
	    public void testTypeClassEmptyCreateInstUnderRootUser() {
            Engine engine = EngineCommonTestUnit.CreateInitEngine();
            Workspace wksp = engine.GetWorkspace();
		
		    // create a project
		    Project prj= wksp.CreateActiveProject("prj");

		    // create a type class
		    EntTypeClass typeClassAdr= prj.CreateTypeClass("Address");
		    Assert.IsNotNull(typeClassAdr, "The typeClass 'Adr' should be created.");
		
		    // create an inst class
		    EntInstClass instClassAdr= prj.createEntInstClass(prj.GetRootUserFolder(), "adr", "Address");
		    Assert.IsNotNull(instClassAdr, "The inst class 'adr' should exists.");

		    // check the type class of the inst
		    EntTypeClass typeClassOfInst= prj.GetTypeClassOfInstClass(instClassAdr);  
		    // check the type class of the inst
		    Assert.IsNotNull(typeClassOfInst,"The type of class should exists.");
		    Assert.AreEqual("Address", typeClassOfInst.GetName(),"The type of class should be 'Address'.");
		
		    // get the tool to find entities in the project
		    EntityFinder entFinder= prj.GetEntityFinder();
		
		    // find the inst class, by the name, scan recursilvy
		    EntInstClass instClassAdrFind =entFinder.FindEntInstClassByName("adr");		
		    Assert.IsNotNull(instClassAdrFind,"The typeClass 'Adr' should be found.");
		
		    // check data members count of the inst class, is empty
		    int nb= instClassAdrFind.getListDataMember().Count;
		    Assert.AreEqual(0,nb, "The inst class 'Address' should contains no data member.");
	    }

	    /**
	     * create an empty typeClass (no DM) and then create an inst of this type class. 
	     */
	    [Test]
	    public void testTypeClassEmptyCreateInstUnderRootUserByDefault() {
            Engine engine = EngineCommonTestUnit.CreateInitEngine();
            Workspace wksp = engine.GetWorkspace();
		
		    // create a project
		    Project prj= wksp.CreateActiveProject("prj");

		    // create a type class
		    EntTypeClass typeClassAdr= prj.CreateTypeClass("Address");
		    Assert.IsNotNull(typeClassAdr,"The typeClass 'Adr' should be created.");
		
		    // create an inst class, under the root user by default
		    EntInstClass instClassAdr= prj.createEntInstClass("Address", "adr");
		    Assert.IsNotNull(instClassAdr,"The inst class 'adr' should exists.");

            // check the type class of the inst
		    EntTypeClass typeClassOfInst= prj.GetTypeClassOfInstClass(instClassAdr);  
		    // check the type class of the inst
		    Assert.IsNotNull(typeClassOfInst,"The type of class should exists.");
		    Assert.AreEqual("Address", typeClassOfInst.GetName(),"The type of class should be 'Address'.");
		
		    // get the tool to find entities in the project
		    EntityFinder entFinder= prj.GetEntityFinder();
		
		    // find the inst class, by the name, scan recursilvy
		    EntInstClass instClassAdrFind =entFinder.FindEntInstClassByName("adr");		
		    Assert.IsNotNull(instClassAdrFind, "The typeClass 'Adr' should be found.");
		
		    // check data members count of the inst class, is empty
		    int nb= instClassAdrFind.getListDataMember().Count;
		    Assert.AreEqual(0,nb,"The inst class 'Address' should contains no data member.");
	    }
	
	
	    /**
	     * create of an inst type that not exists, error. 
	     */
	    [Test]
	    public void testCreateInstClassWithTypeClassUndefined() {
            Engine engine = EngineCommonTestUnit.CreateInitEngine();
            Workspace wksp = engine.GetWorkspace();
		
		    // create a project
		    Project prj= wksp.CreateActiveProject("prj");

		    // create a type class
		    //EntTypeClass typeClassAdr= prj.createTypeClass("Address");
		    //Assert.IsNotNull("The typeClass 'Adr' should be created.",typeClassAdr);
		
		    // create an inst class, under the root user by default
		    EntInstClass instClassAdr= prj.createEntInstClass("adr", "Address");
		    Assert.IsNull(instClassAdr,"The inst class 'adr' should not exists.");
	    }
		
	    /**
	     * create an typeClass with DM and then create an inst of this type class. 
	     */
	    [Test]
	    public void testCreateTypeClassCreateInstWithDM() {
            Engine engine = EngineCommonTestUnit.CreateInitEngine();
            Workspace wksp = engine.GetWorkspace();
		
		    // create a project
		    Project prj= wksp.CreateActiveProject("prj");

		    // create a type class
		    EntTypeClass typeClassAdr= prj.CreateTypeClass("Address");
		    Assert.IsNotNull(typeClassAdr,"The typeClass 'Adr' should be created.");
		    // add data members: street-string
		    EntTypeClassDataMember dmStreet= prj.AddTypeClassDataMember(typeClassAdr, "street", "string");
		    Assert.IsNotNull(dmStreet,"The data member 'Street' of the typeClass should exists.");
				
		    //--create an inst class, under the root user by default
		    EntInstClass instClassAdr= prj.createEntInstClass("Address", "adr");
		    Assert.IsNotNull(instClassAdr,"The inst class 'adr' should exists.");
		    // check the type class of the inst
		    EntTypeClass typeClassOfInst= prj.GetTypeClassOfInstClass(instClassAdr);  
		    // check the type class of the inst
		    Assert.IsNotNull(typeClassOfInst,"The type of class should exists.");
		    Assert.AreEqual("Address", typeClassOfInst.GetName(),"The type of class should be 'Address'.");
		
		    // get the tool to find entities in the project
		    EntityFinder entFinder= prj.GetEntityFinder();
		
		    // find the inst class, by the name, scan recursilvy
		    EntInstClass instClassAdrFind =entFinder.FindEntInstClassByName("adr");		
		    Assert.IsNotNull(instClassAdrFind,"The typeClass 'Adr' should be found.");
		
		    // check data members count of the inst class, is empty
		    int nb= instClassAdrFind.getListDataMember().Count;
		    Assert.AreEqual(1,nb,"The inst class 'Address' should contains one data member.");
		
		    //--check the DM inst (name, type)
		    // get the DM inst
		    EntInstBase instDMStreet= entFinder.FindEntInstClassDataMemberByName(instClassAdrFind, "street");
		    Assert.IsNotNull(instDMStreet,"The inst DM 'street' should be found.");
		    Assert.AreEqual("street",instDMStreet.GetName(),"The inst DM should be named 'street'.");
		
		    // check the type of the inst DM
		    bool isTypeString = prj.IsTypeString(instDMStreet);
		    Assert.AreEqual(true,isTypeString,"The type of the inst DM should be 'string'.");
	    }

    }
}
